﻿using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace GuoZhiQi.MiddleCache.Common.Serialization
{
    [Serializable]
    public  abstract class JsonObjectBase:IJsonObject
    {
        /// <summary>
        /// 忽略为null的属性
        /// </summary>
        [JsonIgnore]
        public virtual bool JsonIgnoreNullProperty { get; set; }

        public JsonObjectBase()
        {
            this.JsonIgnoreNullProperty = false;
        }
        [NonSerialized]
        protected internal bool _jsonInSync;

        /// <summary>
        /// 是否同步json数据
        /// </summary>
        [JsonIgnore]
        public bool JsonInSync {
            get
            {
                return _jsonInSync;
            }
            set
            {
                _jsonInSync = value;
            }
        }
        [NonSerialized]
        internal string _jsonValue;

        /// <summary>
        /// 使json数据失效
        /// </summary>
        public virtual void InvalidateJsonValue()
        {
            this._jsonValue = null;
            this._jsonInSync = false;
        }

        /// <summary>
        /// 序列化对象 转换成json字符串
        /// </summary>
        /// <returns></returns>
        public virtual string ToJson()
        {
            if (this._jsonValue == null || this._jsonInSync == false)
            {
                JsonSerializerSettings settings = new JsonSerializerSettings();
                if (this.JsonIgnoreNullProperty)
                {
                    settings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
                }
                this._jsonValue = JsonConvert.SerializeObject(this, Formatting.None, settings);
            }
            return this._jsonValue;
        }

        /// <summary>
        /// 反序列化json字符串为对象
        /// </summary>
        /// <param name="data"></param>
        public virtual void FromJson(string data)
        {
            Type firstType = this.GetType();
            List<Type> collections = new List<Type>() { typeof(IEnumerable<>), typeof(IEnumerable) };
            foreach (PropertyInfo propertyInfo in firstType.GetProperties())
            {
                if (propertyInfo.CanRead && propertyInfo.CanWrite && propertyInfo.PropertyType != typeof(string) &&
                    (propertyInfo.PropertyType.IsArray || propertyInfo.PropertyType.GetInterfaces().Any(i => collections.Any(c => i == c))))
                {
                    propertyInfo.SetValue(this, null, null);
                }
            }

            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;

            JsonConvert.PopulateObject(data, this);
            this._jsonInSync = false;        
        }
    }
}
